package com.sprouting.ops.service;


import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sprouting.ops.dao.OpsRoleAuthorityDao;
import com.sprouting.ops.dao.OpsRoleDao;
import com.sprouting.ops.dao.OpsUserRoleDao;
import com.sprouting.ops.model.OpsRole;
import com.sprouting.ops.model.OpsRoleAuthority;
import com.sprouting.ops.model.OpsUserRole;
import com.sprouting.ops.model.qo.RoleQo;
import com.sprouting.ops.model.vo.RoleSimpleVo;
import com.sprouting.ops.model.vo.UserCompositeVo;
import com.sprouting.ops.model.vo.UserOwnRoleVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * (Role)表服务实现类
 *
 * @author longx
 * @since 2023-03-19 22:44:34
 */
@Service
@Slf4j
public class OpsRoleService extends ServiceImpl<OpsRoleDao, OpsRole> {

    @Resource
    private OpsRoleDao opsRoleDao;
    @Resource
    private OpsRoleAuthorityDao opsRoleAuthorityDao;
    @Autowired
    private OpsUserRoleDao opsUserRoleDao;


    /**
     * 根据用户ID查询所有的角色
     * @param userId 用户ID
     * @return
     */
    public List<OpsRole> getRoleByUserId(String userId){
        return opsRoleDao.getRoleByUserId(userId);
    }

    /**
     * 根据角色名称查询角色
     * @param code 角色代码
     * @param id 角色ID，注，当传了ID，则会忽略该ID的值
     * @return
     */
    public OpsRole getRoleByCode(String code, String id) {
        return opsRoleDao.getRoleByCode(code, id);
    }

    /**
     * 保存角色和角色与权限关系
     * @param role 角色名称
     * @param rolePowerList 角色与权限关系
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveRole(OpsRole role, List<OpsRoleAuthority> rolePowerList) {
        opsRoleDao.insert(role);
        opsRoleAuthorityDao.insertBatchSomeColumn(rolePowerList);
    }

    /**
     * 更新角色和角色与权限关系
     * @param role 角色
     * @param rolePowerList 角色与权限关系
     */
    @Transactional(rollbackFor = Exception.class)
    public void updRole(OpsRole role, List<OpsRoleAuthority> rolePowerList) {
        //删除旧的关系
        LambdaQueryWrapper<OpsRoleAuthority> delWrapper = new LambdaQueryWrapper<>();
        delWrapper.eq(OpsRoleAuthority::getRoleId, role.getId());
        opsRoleAuthorityDao.delete(delWrapper);

        if (CollUtil.isNotEmpty(rolePowerList)){
            opsRoleAuthorityDao.insertBatchSomeColumn(rolePowerList);
        }

        opsRoleDao.updateById(role);
    }

    /**
     * 根据创建者ID查询用户创建的角色
     * @param createId 角色创建人ID
     * @return
     */
    public List<OpsRole> getRoleByCreateId(String createId) {
        return opsRoleDao.getRoleByCreateId(createId);
    }

    /**
     * 用户拥有的角色
     * @param userId 当前用户ID
     * @return
     */
    public List<OpsRole> getRoleHaveByUserId(String userId) {
        return opsRoleDao.getRoleHaveByUserId(userId);
    }

    /**
     * 分页获取用户拥有的角色
     * @param page 分页参数
     * @param query 查询条件
     * @return
     */
    public Page<OpsRole> getRoleHaveByUserIdPage(Page page, RoleQo query) {
        return opsRoleDao.getRoleHaveByUserIdPage(page, query);
    }

    /**
     * 用户拥有的和创建的角色
     * @param userId 用户ID
     * @return
     */
    public List<UserOwnRoleVo> getUserOwnRole(String userId) {
        List<UserOwnRoleVo> list = opsRoleDao.getUserOwnRole(userId);

        String loginUserId = StpUtil.getLoginIdAsString();
        for (UserOwnRoleVo record : list) {
            if (record.getCreateId().equals(loginUserId)){
                record.setRoleType("create");
            } else {
                record.setRoleType("this");
            }
        }

        return list;
    }

    /**
     * 分页查询自己创建的角色和拥有的角色
     * @param page 分页参数
     * @param query 查询参数
     * @return
     */
    public Page<UserOwnRoleVo> getPage(Page page, RoleQo query) {
        Page<UserOwnRoleVo> rolePage = opsRoleDao.getPage(page, query);
        if (CollUtil.isEmpty(rolePage.getRecords())){
            return rolePage;
        }

        String loginUserId = StpUtil.getLoginIdAsString();
        for (UserOwnRoleVo record : rolePage.getRecords()) {
            if (record.getCreateId().equals(loginUserId)){
                record.setRoleType("create");
            } else {
                record.setRoleType("this");
            }
        }
        return rolePage;
    }

    /**
     * 删除角色
     * @param role 角色
     */
    @Transactional(rollbackFor = Exception.class)
    public void delRole(OpsRole role) {
        LambdaQueryWrapper<OpsRoleAuthority> delWrapper = new LambdaQueryWrapper<>();
        delWrapper.eq(OpsRoleAuthority::getRoleId, role.getId());
        opsRoleAuthorityDao.delete(delWrapper);

        opsRoleDao.deleteById(role.getId());

        LambdaQueryWrapper<OpsUserRole> userRoleWrapper = new LambdaQueryWrapper<>();
        userRoleWrapper.eq(OpsUserRole::getRoleId, role.getId());
        opsUserRoleDao.delete(userRoleWrapper);
    }

    /**
     * 添加用户的角色信息到实体中
     * @param compositeList 要添加的数据
     */
    public void addRole(List<UserCompositeVo> compositeList) {
        if (CollUtil.isEmpty(compositeList)){
            return;
        }

        List<String> userIdList = compositeList.stream().map(UserCompositeVo::getId).collect(Collectors.toList());
        if (CollUtil.isEmpty(userIdList)){
            return;
        }

        List<RoleSimpleVo> userRoleOutList = opsRoleDao.getByUserIdBatch(userIdList);
        if (CollUtil.isEmpty(userRoleOutList)){
            return;
        }

        // 用户id -> 角色
        Map<String, List<RoleSimpleVo>> map = userRoleOutList.stream().collect(Collectors.groupingBy(RoleSimpleVo::getUserId));
        for (UserCompositeVo composite : compositeList) {
            // 获取到角色
            composite.setRoleList(map.get(composite.getId()));
        }
    }
}

